/**************************************************************************
File:        micromachine.cpp
Description:

Copyright:   (C) 2001 by ZJ Laczik
Email:       Zsolt.Laczik@eng.ox.ac.uk
****************************************************************************
Change log:
   begin      Fri Mar 16 11:54:32 GMT 2001
   15/2/2012	QT4 update
***************************************************************************/

#include <QWidget>
#include <QPlainTextEdit>
#include <QFileDialog>
#include <QMessageBox>
#include <QTextStream>
#include <QClipboard>

#include "micromachine.h"

Hal* gHal;

Micromachine::Micromachine(QWidget * parent, Qt::WindowFlags f)
        : QMainWindow ( parent, f )
{
    setAttribute(Qt::WA_DeleteOnClose);

    createActions();
    initMenuBar();
    initStatusBar();
    initFrontPanel();
    initStepperTimingDlg();

    mHal = new Hal(this);
    gHal = mHal;
    mPositioner = new Positioner(this);
    mLaser = new Laser(this);
    mBatchProc = new BatchProcessor(this);

    initConnections();
    setDefaults();

    readSettings();

    QApplication::clipboard()->clear();
}

Micromachine::~Micromachine() {
}

void Micromachine::setDefaults() {
    viewStatusBarAct->setChecked(true);

    viewPosDspZoom10Act->setChecked(true);
    mFrontPanel->mZoom10x->setChecked(true);
    mFrontPanel->mPosDsp->SetZoom(10.0);

    mFrontPanel->slotDspPos(0.0,0.0,0.0);	// ToDo set this to position value saved on exit
    mFrontPanel->mPosDsp->EnableMoves(true);
    
    settingIP28Ctrl->setEnabled(mHal->mfIP28IsReady());
    settingZJLPPCtrl->setEnabled(mHal->mfZJLPPIsReady());
    settingComediUSBDUXCtrl->setEnabled(mHal->mfUSBDUXIsReady());

    settingDummyCtrl->setChecked(true);
    
    settingLaserInterlockDisable->setChecked(false);

    mLaser->SetNPulses(10);
    mLaser->SetRepRate(100);
    mLaser->SetTriggerDelay(0);
    
    mPositioner->stepper.slotSetMinFreq(100);
    mPositioner->stepper.slotSetMaxFreq(500);
    mPositioner->stepper.slotSetFreqIncr(50);
    mPositioner->stepper.slotSetPulseWidth(1000);
    
    setCurrentFile("");

    mFrontPanel->mBatch->slotCreateDefaultBatchfile();
    mFrontPanel->mBatch->MakeLib();
    mFrontPanel->mBatch->document()->setModified(false);
    
    editCutAct->setEnabled(false);
    editCopyAct->setEnabled(false);

    statusBar()->showMessage(IDS_STATUS_DEFAULT);
}

void Micromachine::initConnections() {

    // connect actions to slots
    connect(fileNewAct, 		SIGNAL(triggered()),
            this, 			SLOT(slotFileNew()));
    connect(fileOpenAct, 		SIGNAL(triggered()),
            this, 			SLOT(slotFileOpen()));
    connect(fileSaveAct, 		SIGNAL(triggered()),
            this, 			SLOT(slotFileSave()));
    connect(fileSaveAsAct, 		SIGNAL(triggered()),
            this, 			SLOT(slotFileSaveAs()));
    connect(fileQuitAct, 		SIGNAL(triggered()),
            this, 			SLOT(slotFileQuit()));
    connect(viewStatusBarAct, 		SIGNAL(triggered()),
            this, 			SLOT(slotViewStatusBar()));
    connect(viewPosDspZooms, 		SIGNAL(triggered(QAction*)),
            this, 			SLOT(slotPosDspZoom(QAction*)));
    connect(helpAboutAct, 		SIGNAL(triggered()),
            this, 			SLOT(slotHelpAbout()));

    connect(settingStepperTiming, 	SIGNAL(triggered()),
            mStepperTiming, 		SLOT(show()));

    // connect submenu signals to status display slots
    connect(fileMenu, 			SIGNAL(hovered(QAction*)),
            this, 			SLOT(slotStatusActionCallback(QAction*)));
    connect(viewMenu, 			SIGNAL(hovered(QAction*)),
            this, 			SLOT(slotStatusActionCallback(QAction*)));
    connect(helpMenu, 			SIGNAL(hovered(QAction*)),
            this, 			SLOT(slotStatusActionCallback(QAction*)));

    // stepper timing dialogue
   connect(mStepperTiming->mMinFreq,		SIGNAL(ValueChanged(int)),
           &(mPositioner->stepper),		SLOT(slotSetMinFreq(int)));
    connect(mStepperTiming->mMaxFreq,		SIGNAL(ValueChanged(int)),
            &(mPositioner->stepper),		SLOT(slotSetMaxFreq(int)));
    connect(mStepperTiming->mFreqIncr,		SIGNAL(ValueChanged(int)),
            &(mPositioner->stepper),		SLOT(slotSetFreqIncr(int)));
    connect(mStepperTiming->mPulseWidth,	SIGNAL(ValueChanged(long int)),
            &(mPositioner->stepper),		SLOT(slotSetPulseWidth(long int)));
    
   connect(&(mPositioner->stepper),		SIGNAL(sigMinFreqChanged(int)),
           mStepperTiming->mMinFreq,		SLOT(Update(int)));
   connect(&(mPositioner->stepper),		SIGNAL(sigMaxFreqChanged(int)),
           mStepperTiming->mMaxFreq,		SLOT(Update(int)));
   connect(&(mPositioner->stepper),		SIGNAL(sigFreqIncrChanged(int)),
           mStepperTiming->mFreqIncr,		SLOT(Update(int)));
   connect(&(mPositioner->stepper),		SIGNAL(sigPulseWidthChanged(long int)),
           mStepperTiming->mPulseWidth,		SLOT(Update(long int)));

    // Text to DLL contents change signal
    connect(mFrontPanel->mBatch->document(),	SIGNAL(contentsChanged()),
	    this,				SLOT(slotDocumentWasModified()));

    connect(mFrontPanel->mBatch,		SIGNAL(undoAvailable(bool)),
             editUndoAct,			SLOT(setEnabled(bool)));
    connect(mFrontPanel->mBatch,		SIGNAL(redoAvailable(bool)),
             editRedoAct,			SLOT(setEnabled(bool)));
    connect(mFrontPanel->mBatch,		SIGNAL(copyAvailable(bool)),
             editCutAct,			SLOT(setEnabled(bool)));
     connect(mFrontPanel->mBatch,		SIGNAL(copyAvailable(bool)),
             editCopyAct,			SLOT(setEnabled(bool)));
    // ToDo: paste available

      // also connect the various edit signals
     connect(editUndoAct,			SIGNAL(triggered()),
	     mFrontPanel->mBatch,		SLOT(undo()));
     connect(editRedoAct,			SIGNAL(triggered()),
	     mFrontPanel->mBatch,		SLOT(redo()));
     connect(editCutAct,			SIGNAL(triggered()),
	     mFrontPanel->mBatch,		SLOT(cut()));
     connect(editCopyAct,			SIGNAL(triggered()),
	     mFrontPanel->mBatch,		SLOT(copy()));
     connect(editPasteAct,			SIGNAL(triggered()),
	     mFrontPanel->mBatch,		SLOT(paste()));

     // setting controllers connections
     connect(settingDummyCtrl,			SIGNAL(triggered()),
	     mHal,				SLOT(slotSelectDummyCtrl()));
     connect(settingIP28Ctrl,			SIGNAL(triggered()),
	     mHal,				SLOT(slotSelectIP28Ctrl()));
     connect(settingComediUSBDUXCtrl,		SIGNAL(triggered()),
	     mHal,				SLOT(slotSelectComediUSBDUXCtrl()));
     connect(settingZJLPPCtrl,			SIGNAL(triggered()),
	     mHal,				SLOT(slotSelectZJLPPCtrl()));
     
    // QT About message box
    connect(helpAboutQtAct,		SIGNAL(triggered()),
	    qApp,			SLOT(aboutQt()));

    // connect front panel button signals
    connect(mFrontPanel->singleShot,	SIGNAL(clicked()),
            mLaser, 			SLOT(Fire()));
    connect(mFrontPanel->continuous,	SIGNAL(clicked()),
            mLaser, 			SLOT(ContFire()));
    connect(mFrontPanel->burst,		SIGNAL(clicked()),
            mLaser, 			SLOT(Burst()));
    connect(mFrontPanel->stop,		SIGNAL(clicked()),
            mLaser, 			SLOT(Stop()));

    connect(mFrontPanel->startBatch,	SIGNAL(clicked()),
            mBatchProc, 		SLOT(Run()));
    connect(mFrontPanel->stop,		SIGNAL(clicked()),
            mBatchProc, 		SLOT(Stop()));
    connect(mFrontPanel->stop,		SIGNAL(clicked()),
            mPositioner, 		SLOT(Stop()));

    connect(mFrontPanel->mZoom1x,	SIGNAL(pressed()),
            viewPosDspZoom1Act, 	SLOT(trigger()));
    connect(mFrontPanel->mZoom10x,	SIGNAL(pressed()),
            viewPosDspZoom10Act, 	SLOT(trigger()));
    connect(mFrontPanel->mZoom100x,	SIGNAL(pressed()),
            viewPosDspZoom100Act, 	SLOT(trigger()));
    connect(mFrontPanel->mZoom1000x,	SIGNAL(pressed()),
            viewPosDspZoom1000Act, 	SLOT(trigger()));

    connect(viewPosDspZoom1Act,		SIGNAL(triggered(bool)),
            mFrontPanel->mZoom1x, 	SLOT(setChecked(bool)));
    connect(viewPosDspZoom10Act,	SIGNAL(triggered(bool)),
            mFrontPanel->mZoom10x, 	SLOT(setChecked(bool)));
    connect(viewPosDspZoom100Act,	SIGNAL(triggered(bool)),
            mFrontPanel->mZoom100x, 	SLOT(setChecked(bool)));
    connect(viewPosDspZoom1000Act,	SIGNAL(triggered(bool)),
            mFrontPanel->mZoom1000x, 	SLOT(setChecked(bool)));
    
    // connect laser stop (due to e.g. interlock fail) to other stops
    connect(mLaser,			SIGNAL(sigStop()),
            mFrontPanel->stop, 		SIGNAL(clicked()));

    // connect laser param. line edits
    connect(mFrontPanel->mNPulse,	SIGNAL(ValueChanged(int)),
            mLaser, 			SLOT(SetNPulses(int)));
    connect(mFrontPanel->mRepRate,	SIGNAL(ValueChanged(int)),
            mLaser, 			SLOT(SetRepRate(int)));
    connect(mFrontPanel->mDelay,	SIGNAL(ValueChanged(long int)),
            mLaser, 			SLOT(SetTriggerDelay(long int)));

    connect(mLaser,			SIGNAL(NPulsesChanged(int)),
            mFrontPanel->mNPulse, 	SLOT(Update(int)));
    connect(mLaser,			SIGNAL(RepRateChanged(int)),
            mFrontPanel->mRepRate, 	SLOT(Update(int)));
    connect(mLaser,			SIGNAL(TriggerDelayChanged(long int)),
            mFrontPanel->mDelay, 	SLOT(Update(long int)));

    // connect front panel batch edit box signals
    connect(mFrontPanel->mBatch,	SIGNAL(LibHasChanged(const char *)),
            mBatchProc, 		SLOT(NewBatchFnDefined(const char *)));

    // connect batch processor to positioner and laser
    connect(mBatchProc,			SIGNAL(SigMoveXTo(float)),
            mPositioner, 		SLOT(MoveXTo(float)));
    connect(mBatchProc,			SIGNAL(SigMoveYTo(float)),
            mPositioner, 		SLOT(MoveYTo(float)));
    connect(mBatchProc,			SIGNAL(SigMoveZTo(float)),
            mPositioner, 		SLOT(MoveZTo(float)));
    connect(mBatchProc,			SIGNAL(SigMoveTo(float, float, float)),
            mPositioner, 		SLOT(MoveTo(float, float, float)));

    connect(mBatchProc,			SIGNAL(SigBurst()),
            mLaser, 			SLOT(Burst()));
    connect(mBatchProc,			SIGNAL(SigFire()),
            mLaser, 			SLOT(Fire()));

    // connect type-in move requests
    connect(mFrontPanel->mXPosLE,	SIGNAL(ValueChanged(float)),
            mPositioner, 		SLOT(MoveXTo(float)));
    connect(mFrontPanel->mYPosLE,	SIGNAL(ValueChanged(float)),
            mPositioner, 		SLOT(MoveYTo(float)));
    connect(mFrontPanel->mZPosLE,	SIGNAL(ValueChanged(float)),
            mPositioner, 		SLOT(MoveZTo(float)));

    // connect mouse move requests to positioner
    connect(mFrontPanel->mPosDsp,	SIGNAL(Move(int, float)),
            mPositioner, 		SLOT(Move(int, float)));
    connect(mFrontPanel->mPosDsp,	SIGNAL(MoveTo(float, float, float)),
            mPositioner, 		SLOT(MoveTo(float, float, float)));

    // connect pos. report to LCD and 3D position dsplays
    connect(mPositioner, 		SIGNAL(Position(float,float,float)),
            mFrontPanel,		SLOT(slotDspPos(float, float, float)));

    // connect status reporting
    connect(mFrontPanel->mBatch,	SIGNAL(StatusMsg(const QString &, bool)),
            mFrontPanel,		SLOT(slotDspMsg(QString,bool)));
    connect(mLaser,			SIGNAL(StatusMsg(const QString &, bool)),
            mFrontPanel,		SLOT(slotDspMsg(QString,bool)));
    connect(mPositioner,		SIGNAL(StatusMsg(const QString &, bool)),
            mFrontPanel,		SLOT(slotDspMsg(QString,bool)));
    connect(mBatchProc,			SIGNAL(StatusMsg(const QString &, bool)),
            mFrontPanel,		SLOT(slotDspMsg(QString,bool)));
    connect(mHal,			SIGNAL(signalDspMsg(const QString &, bool)),
            mFrontPanel,		SLOT(slotDspMsg(QString, bool)));

    // connect GUI enable/disable
    connect(mLaser,			SIGNAL(Running(bool)),
            mFrontPanel,		SLOT(slotDisableControls(bool)));
    connect(mPositioner,		SIGNAL(Running(bool)),
            mFrontPanel,		SLOT(slotDisableControls(bool)));
    connect(mBatchProc,			SIGNAL(Running(bool)),
            mFrontPanel,		SLOT(slotDisableControls(bool)));
}

void Micromachine::closeEvent( QCloseEvent* ce ) {
    if (maybeSave()) {
        writeSettings();
        ce->accept();
    } else {
        ce->ignore();
    }
}

void Micromachine::createActions()
{
    // Create actions

    // File menu

    // New
    fileNewAct = new QAction(QIcon(":/images/new.png"), "&New", this);
    fileNewAct->setShortcuts(QKeySequence::New);
    fileNewAct->setStatusTip("Create a new file");
    // Open
    fileOpenAct = new QAction(QIcon(":/images/open.png"), "&Open", this);
    fileOpenAct->setShortcuts(QKeySequence::Open);
    fileOpenAct->setStatusTip("Open an existing file");
    // Save
    fileSaveAct = new QAction(QIcon(":/images/save.png"), "&Save", this);
    fileSaveAct->setShortcuts(QKeySequence::Save);
    fileSaveAct->setStatusTip("Save file");
    // Save As
    fileSaveAsAct = new QAction(QIcon(":/images/saveas.png"), "Save &As", this);
    fileSaveAsAct->setShortcuts(QKeySequence::SaveAs);
    fileSaveAsAct->setStatusTip("Save file with new name");
    // Quit
    fileQuitAct = new QAction(QIcon(":/images/quit.png"), "&Quit", this);
    fileQuitAct->setShortcuts(QKeySequence::Quit);
    fileQuitAct->setStatusTip("Quit");

    // Edit menu

    // Undo
    editUndoAct = new QAction(QIcon(":/images/undo.png"), "&Undo", this);
    editUndoAct->setShortcuts(QKeySequence::Undo);
    editUndoAct->setStatusTip("Undo last edit");
    // Redo
    editRedoAct = new QAction(QIcon(":/images/redo.png"), "Re&do", this);
    editRedoAct->setShortcuts(QKeySequence::Redo);
    editRedoAct->setStatusTip("Redo last edit");
    
    // Cut
    editCutAct = new QAction(QIcon(":/images/cut.png"), "Cu&t", this);
    editCutAct->setShortcuts(QKeySequence::Cut);
    editCutAct->setStatusTip("Cut text to the clipboard");
    // Copy
    editCopyAct = new QAction(QIcon(":/images/copy.png"), "&Copy", this);
    editCopyAct->setShortcuts(QKeySequence::Copy);
    editCopyAct->setStatusTip("Copy text to the clipboard");
    // Paste
    editPasteAct = new QAction(QIcon(":/images/paste.png"), "&Paste", this);
    editPasteAct->setShortcuts(QKeySequence::Paste);
    editPasteAct->setStatusTip("Paste text from the clipboard");
    
    // View menu

    // Statusbar visibility
    viewStatusBarAct = new QAction(QIcon(":/images/statusbar.png"), "&Statusbar", this);
    viewStatusBarAct->setStatusTip("Toggle visibility of statusbar");
    viewStatusBarAct->setCheckable(true);

    // Position display zoom
    viewPosDspZoom1Act = new QAction(QIcon(":/images/zoom.png"), "&Position display zoom 1x", this);
    viewPosDspZoom1Act->setStatusTip("Change position display zoom level to 1x");
    viewPosDspZoom1Act->setCheckable(true);
    viewPosDspZoom10Act = new QAction(QIcon(":/images/zoom.png"), "&Position display zoom 10x", this);
    viewPosDspZoom10Act->setStatusTip("Change position display zoom level to 10x");
    viewPosDspZoom10Act->setCheckable(true);
    viewPosDspZoom100Act = new QAction(QIcon(":/images/zoom.png"), "&Position display zoom 100x", this);
    viewPosDspZoom100Act->setStatusTip("Change position display zoom level to 100x");
    viewPosDspZoom100Act->setCheckable(true);
    viewPosDspZoom1000Act = new QAction(QIcon(":/images/zoom.png"), "&Position display zoom 1000x", this);
    viewPosDspZoom1000Act->setStatusTip("Change position display zoom level to 1000x");
    viewPosDspZoom1000Act->setCheckable(true);

    viewPosDspZooms = new QActionGroup(this);
    viewPosDspZooms->addAction(viewPosDspZoom1Act);
    viewPosDspZooms->addAction(viewPosDspZoom10Act);
    viewPosDspZooms->addAction(viewPosDspZoom100Act);
    viewPosDspZooms->addAction(viewPosDspZoom1000Act);
    viewPosDspZooms->setExclusive(true);
    
    // Settings menu

    settingDummyCtrl = new QAction(QIcon(":/images/dummy.png"), "&No-op Dummy controller", this);
    settingDummyCtrl->setCheckable(true);
    settingIP28Ctrl = new QAction(QIcon(":/images/dummy.png"), "&IP28 controller", this);
    settingIP28Ctrl->setCheckable(true);
    settingZJLPPCtrl = new QAction(QIcon(":/images/dummy.png"), "&Parallel port controller", this);
    settingZJLPPCtrl->setCheckable(true);
    settingComediUSBDUXCtrl = new QAction(QIcon(":/images/dummy.png"), "&USBDUX / Comedi controller", this);
    settingComediUSBDUXCtrl->setCheckable(true);

    settingControllers = new QActionGroup(this);
    settingControllers->addAction(settingDummyCtrl);
    settingControllers->addAction(settingIP28Ctrl);
    settingControllers->addAction(settingZJLPPCtrl);
    settingControllers->addAction(settingComediUSBDUXCtrl);
    settingControllers->setExclusive(true);

    settingStepperTiming = new QAction(QIcon(":/images/dummy.png"), "Stepper motor timing", this);

    settingLaserInterlockDisable = new QAction(QIcon(":/images/dummy.png"), "Disable laser interlock", this);
    settingLaserInterlockDisable->setCheckable(true);

    // Help menu

    // About Qt
    helpAboutQtAct = new QAction(tr("About &Qt"), this);
    helpAboutQtAct->setStatusTip(tr("Show Qt library version information"));
    // About
    helpAboutAct = new QAction(QIcon(":/images/about.png"), "&About", this);
    helpAboutAct->setStatusTip("Show program version information");
}

void Micromachine::initMenuBar()
{
    // Add menus to menu bar

    fileMenu = menuBar()->addMenu("&File");
    editMenu = menuBar()->addMenu("&Edit");
    viewMenu = menuBar()->addMenu("&View");
    settingsMenu = menuBar()->addMenu("&Settings");
    menuBar()->addSeparator();
    helpMenu = menuBar()->addMenu("&Help");


    // add actions to menus

    fileMenu->addAction(fileNewAct);
    fileMenu->addAction(fileOpenAct);
    fileMenu->addSeparator();
    fileMenu->addAction(fileSaveAct);
    fileMenu->addAction(fileSaveAsAct);
    fileMenu->addSeparator();
    fileMenu->addAction(fileQuitAct);

    editMenu->addAction(editUndoAct);
    editMenu->addAction(editRedoAct);
    editMenu->addSeparator();
    editMenu->addAction(editCutAct);
    editMenu->addAction(editCopyAct);
    editMenu->addAction(editPasteAct);

    viewMenu->addAction(viewStatusBarAct);
    viewMenu->addSeparator();
    viewMenu->addAction(viewPosDspZoom1Act);
    viewMenu->addAction(viewPosDspZoom10Act);
    viewMenu->addAction(viewPosDspZoom100Act);
    viewMenu->addAction(viewPosDspZoom1000Act);

    settingsMenu->addAction(settingDummyCtrl);
    settingsMenu->addAction(settingIP28Ctrl);
    settingsMenu->addAction(settingZJLPPCtrl);
    settingsMenu->addAction(settingComediUSBDUXCtrl);
    
    settingsMenu->addSeparator();
    settingsMenu->addAction(settingStepperTiming);
    
    settingsMenu->addSeparator();
    settingsMenu->addAction(settingLaserInterlockDisable);

    helpMenu->addAction(helpAboutQtAct);
    helpMenu->addAction(helpAboutAct);
}

void Micromachine::initStatusBar()
{
    statusBar()->showMessage(IDS_STATUS_DEFAULT, 10000);
}

void Micromachine::initFrontPanel()
{
    mFrontPanel = new FrontPanel(this);
    setCentralWidget(mFrontPanel);

    mHeightWithStatus = mFrontPanel->height()+menuBar()->height()+statusBar()->height();
    mHeight = mFrontPanel->height()+menuBar()->height();

    setFixedSize(mFrontPanel->width(), mHeightWithStatus);
}

void Micromachine::initStepperTimingDlg()
{
    mStepperTiming = new StepperTiming();
    
//    mStepperTiming->show();
}

void Micromachine::slotFileNew()
{
    statusBar()->showMessage("Creating new file file...");
    if (maybeSave()) {
        mFrontPanel->mBatch->clear();
        mFrontPanel->mBatch->slotCreateDefaultBatchfile();
        mFrontPanel->mBatch->MakeLib();
        mFrontPanel->mBatch->document()->setModified(false);

        setCurrentFile("");
    }
}

void Micromachine::slotFileOpen()
{
    statusBar()->showMessage("Opening file...");
    if (maybeSave()) {
        QString fileName = QFileDialog::getOpenFileName(this);
        if (!fileName.isEmpty())
            loadFile(fileName);
    }
}

bool Micromachine::slotFileSave()
{
    statusBar()->showMessage("Saving file...");
    if (curFile.isEmpty()) {
        return slotFileSaveAs();
    } else {
        return saveFile(curFile);
    }
}

bool Micromachine::slotFileSaveAs()
{
    statusBar()->showMessage("Saving file under new filename...");
    QString fileName = QFileDialog::getSaveFileName(this);
    if (fileName.isEmpty())
        return false;

    return saveFile(fileName);
}

void Micromachine::slotFileQuit()
{
    statusBar()->showMessage("Exiting application...");
    if (!close())
        statusBar()->showMessage(IDS_STATUS_DEFAULT);
}

void Micromachine::slotViewStatusBar()
{
    statusBar()->showMessage("Toggle statusbar...");

    if (statusBar()->isVisible()) {
        statusBar()->hide();
        setFixedSize(mFrontPanel->width(), mHeight);
        viewStatusBarAct->setChecked(false);
    }
    else {
        statusBar()->show();
        setFixedSize(mFrontPanel->width(), mHeightWithStatus);

        viewStatusBarAct->setChecked(true);
    }

    statusBar()->showMessage(IDS_STATUS_DEFAULT);
}

void Micromachine::slotPosDspZoom(QAction* a)
{
    if (a == viewPosDspZoom1Act) {
        statusBar()->showMessage("Position display 1x zoom selected");
        (mFrontPanel->mPosDsp)->SetZoom(1.0);
    }
    else if (a == viewPosDspZoom10Act) {
        statusBar()->showMessage("Position display 10x zoom selected");
        (mFrontPanel->mPosDsp)->SetZoom(10.0);
    }
    else if (a == viewPosDspZoom100Act) {
        statusBar()->showMessage("Position display 100x zoom selected");
        (mFrontPanel->mPosDsp)->SetZoom(100.0);
    }
    else if (a == viewPosDspZoom1000Act) {
        statusBar()->showMessage("Position display 1000x zoom selected");
        (mFrontPanel->mPosDsp)->SetZoom(1000.0);
    }
}

void Micromachine::slotHelpAbout()
{
    QMessageBox::about(this,"About...",
                       IDS_APP_ABOUT );
}

void Micromachine::slotStatusHelpMsg(const QString &text)
{
    statusBar()->showMessage(text, 10000);
}

void Micromachine::slotStatusActionCallback(QAction* a)
{
    slotStatusHelpMsg(a->statusTip());
}

void Micromachine::slotDocumentWasModified()
{
    setWindowModified(mFrontPanel->mBatch->document()->isModified());
}

bool Micromachine::maybeSave()
{
    if (mFrontPanel->mBatch->document()->isModified()) {
        QMessageBox::StandardButton ret;
        ret = QMessageBox::warning(this, "Micromachininig Controller",
                                   "The batch file has been modified.\n"
                                   "Do you want to save your changes?",
                                   QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
        if (ret == QMessageBox::Save)
            return slotFileSave();
        else if (ret == QMessageBox::Cancel)
            return false;
    }
    return true;
}

void Micromachine::loadFile(const QString &fileName)
{
    QFile file(fileName);
    if (!file.open(QFile::ReadOnly | QFile::Text)) {
        QMessageBox::warning(this, "Micromachininig Controller",
                             QString("Cannot read file %1:\n%2.")
                             .arg(fileName)
                             .arg(file.errorString()));
        return;
    }

    QTextStream in(&file);
    QApplication::setOverrideCursor(Qt::WaitCursor);
    mFrontPanel->mBatch->setPlainText(in.readAll());
    QApplication::restoreOverrideCursor();

    setCurrentFile(fileName);
    statusBar()->showMessage("File loaded", 2000);
}

bool Micromachine::saveFile(const QString &fileName)
{
    QFile file(fileName);
    if (!file.open(QFile::WriteOnly | QFile::Text)) {
        QMessageBox::warning(this, "Micromachininig Controller",
                             QString("Cannot write file %1:\n%2.")
                             .arg(fileName)
                             .arg(file.errorString()));
        return false;
    }

    QTextStream out(&file);
    QApplication::setOverrideCursor(Qt::WaitCursor);
    out << mFrontPanel->mBatch->toPlainText();
    QApplication::restoreOverrideCursor();

    setCurrentFile(fileName);
    statusBar()->showMessage("File saved", 2000);
    return true;
}

void Micromachine::setCurrentFile(const QString &fileName)
{
    curFile = fileName;

    QString shownName = curFile;
    if (curFile.isEmpty())
        shownName = "untitled.cpp";
    setWindowFilePath(shownName);
    setWindowTitle("Micromachining Workstation - "+strippedName(shownName)+"[*]");

    mFrontPanel->mBatch->document()->setModified(false);
    setWindowModified(false);
}

void Micromachine::readSettings()
{
    /*
         QSettings settings("Trolltech", "Application Example");
         QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
         QSize size = settings.value("size", QSize(400, 400)).toSize();
         resize(size);
         move(pos);
    */
}

void Micromachine::writeSettings()
{
    /*
          QSettings settings("Trolltech", "Application Example");
         settings.setValue("pos", pos());
         settings.setValue("size", size());
    */
}

QString Micromachine::strippedName(const QString &fullFileName)
{
  return QFileInfo(fullFileName).fileName();
}
